﻿# encoding:utf-8
import logging
import sys, os, traceback
import json
import traceback
import time
from datetime import datetime, date
from wxpyBase import *

g_logger = None
g_loggerErr = None
g_errFile = None

# 默认在主文件路径下建 ./tmp/log/ 文件夹按日期放日志文件
def initLogger(logFilePath=None, logErrFilePath=None):
    global g_logger
    if g_logger is not None:
        # print('g_logger is not None')
        return

    if logFilePath is None:
        logFilePath = getDefaultLogFilePath()
    if logErrFilePath is None:
        logErrFilePath = getDefaultErrLogFilePath()

    try:
        logger = logging.getLogger(os.path.basename(sys.argv[0]))
        logger.setLevel(logging.INFO)
        rf_handler = logging.StreamHandler(sys.stderr)#默认是sys.stderr
        rf_handler.setLevel(logging.INFO) 
        #rf_handler = logging.handlers.TimedRotatingFileHandler('all.log', when='midnight', interval=1, backupCount=7, atTime=datetime.time(0, 0, 0, 0))
        rf_handler.setFormatter(logging.Formatter("%(asctime)s %(message)s"))
        
        f_handler = logging.FileHandler(logFilePath, encoding='utf-8')
        f_handler.setLevel(logging.INFO)
        f_handler.setFormatter(logging.Formatter("%(asctime)s %(message)s"))
        
        logger.addHandler(rf_handler)
        logger.addHandler(f_handler)

        # logger.debug('debug message😂')
        # logger.info('info message😂')
        # logger.warning('warning message😂')
        # logger.error('error message我有个adi的..😂😂😂')
        # logger.critical('critical message😂')
        
        g_logger = logger

        loggerErr = logging.getLogger('wxpyErrLogger')
        loggerErr.setLevel(logging.ERROR)
        # rf_handlerErr = logging.StreamHandler(sys.stderr)#默认是sys.stderr
        # rf_handlerErr.setLevel(logging.ERROR) 
        # rf_handlerErr.setFormatter(logging.Formatter("%(asctime)s %(filename)s[:%(lineno)d] - %(message)s"))
        
        f_handlerErr = logging.FileHandler(logErrFilePath, encoding='utf-8')
        f_handlerErr.setLevel(logging.ERROR)
        f_handlerErr.setFormatter(logging.Formatter("%(asctime)s %(filename)s[:%(lineno)d] - %(message)s"))
        
        # 注释掉为了不输出到 console
        # loggerErr.addHandler(rf_handlerErr)
        loggerErr.addHandler(f_handlerErr)
        global g_loggerErr
        g_loggerErr = loggerErr
        global g_errFile
        g_errFile = open(getDefaultErrLogFilePath(),'a+')
    except Exception as e:
        dealException()
        print('initLogge err: '+str(e))
    

# 打印 info 级日志
def logInfo(str):
    initLogger()
    g_logger.info(str)

# 打印 error 级日志，会输出到正常日志文件及错误日志文件中
def logError(str):
    initLogger()
    g_logger.info(str)
    g_loggerErr.error(str)

# 扩展 json 无法解析的类型
class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            # return obj.strftime('%Y-%m-%d %H:%M:%S')
            return str(obj)
        elif isinstance(obj, date):
            # return obj.strftime('%Y-%m-%d')
            return str(obj)
        else:
            try:
                return json.JSONEncoder.default(self, obj)
            except Exception as e:
                logError('type not support: '+str(obj))
                return str(obj)
                
# json 对齐方式输出对象所有属性，方便查看
def obj2JsonStr(obj):
    desc = obj
    if hasattr(obj,'__dict__'):
        desc = obj.__dict__

    try:
        # ensure_ascii=False 中文不变成百分符
        # indent 缩进行增加的空格数
        j = json.dumps(desc, cls=ComplexEncoder, ensure_ascii=False, indent=4)
        return str(j)
    except Exception as e:
        logError('obj2JsonSt err: '+str(e))
        traceback.print_exc()

# 默认日志路径
def getDefaultLogPath():
    path = os.path.dirname(sys.argv[0])
    path = path + os.sep + 'tmp' + os.sep + 'log'
    path = path + os.sep + os.path.basename(sys.argv[0])
    path = path + '_' + time.strftime('%Y-%m-%d',time.localtime(time.time()))
    return path

# 取默认日志文件路径
def getDefaultLogFilePath():
    path = getDefaultLogPath() + '.log'
    return path

# 取默认错误日志路径，与普通日志分开
def getDefaultErrLogFilePath():
    path = getDefaultLogPath() + '_err.log'
    return path

# 统一处理异常
def dealException():
    # 打印错误信息
    traceback.print_exc()
    if g_errFile is not None:
        #打印到文件
        traceback.print_exc(file=g_errFile)

# 测试
if __name__ == '__main__':
    initLogger()
    logInfo('测试日志INFO😂')
    try:
        1/0
    except Exception as e:
        dealException()
        logError('uploadImgToServe err: '+str(e))
        